﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.Objects;

namespace eStore.Models
{
	public class CartRepository:ICartRepository
	{
		private eStoreContainer _container = null;

		public CartRepository() {
			_container = new eStoreContainer();
		}

		public Cart SubmitCart(Cart cart)
		{
			try
			{
				_container.Carts.AddObject(cart);
				_container.SaveChanges();
			}
			catch (Exception)
			{

				throw;
			}
			return cart;
		}

		public Cart AddProduct(string sId, Product productItem)
		{
			var matchedCart = (from cart in _container.Carts
							   where cart.SessionId == sId
							   select cart).FirstOrDefault();
			var matchedCartWithProduct = matchedCart.CartItems.Where((x) => x.Product.ProductId == productItem.ProductId);
			if (matchedCartWithProduct.Any())
			{
				var oCartItem = matchedCartWithProduct.FirstOrDefault();
				oCartItem.CartItemQty++;
			}
			else {
				CartItem oNewCartItem = new CartItem();
				oNewCartItem.CartItemQty = 1;
				oNewCartItem.CartRecordId = matchedCart.RecordId;
				oNewCartItem.ProductProductId = productItem.ProductId;
				matchedCart.CartItems.Add(oNewCartItem);
			}
			_container.SaveChanges();
			UpdateReCalItemsCount(matchedCart);

			return matchedCart;
			
		}

		private void UpdateReCalItemsCount(Cart matchedCart)
		{
		 try 
			{	        
					var totalItems = matchedCart.CartItems.Sum(x => x.CartItemQty);
				matchedCart.CartQty = totalItems;
				_container.SaveChanges();
			}
		 catch (OptimisticConcurrencyException)
			{
				_container.Refresh(RefreshMode.ClientWins, matchedCart);
				
			}
		}

		public Cart AddProduct(Cart cart, Product productItem)
		{
		   
			var matchedCartWithProduct = cart.CartItems.Where((x) => x.Product.ProductId == productItem.ProductId);
			if (matchedCartWithProduct.Any())
			{
				var oCartItem = matchedCartWithProduct.FirstOrDefault();
				oCartItem.CartItemQty++;
			}            
			else {
				CartItem oNewCartItem = new CartItem();
				oNewCartItem.CartItemQty = 1;
				oNewCartItem.CartRecordId = cart.RecordId;
				oNewCartItem.ProductProductId = productItem.ProductId;
				cart.CartItems.Add(oNewCartItem);
			}

			_container.SaveChanges();
			return cart;

		}

		public Cart AddCartItem(Cart cart,CartItem cartItem)
		{
			if (cart != null)
			{
				var matchedCartItem = cart.CartItems.Where(x => x.ProductProductId == cartItem.ProductProductId);
				if (matchedCartItem.Any())
				{
					var firstCartItem = matchedCartItem.FirstOrDefault();
					firstCartItem.CartItemQty += 1;
				}else{
					cart.CartItems.Add(cartItem);
				}
			}
			_container.SaveChanges();
			UpdateReCalItemsCount(cart);
			return cart;
		}

		public Cart AddCartItem(string sId, CartItem cartItem)
		{
			var matchedCart = (from cart in _container.Carts
							   where cart.SessionId == sId
							   select cart).FirstOrDefault();
			if (matchedCart != null)
			{
				return AddCartItem(matchedCart, cartItem);
			}
			return null;
		}

		public Cart DeleteCartItem(CartItem carteItem)
		{
			var parentCart = carteItem.Cart;
			try
			{
				_container.CartItems.DeleteObject(carteItem);
				_container.SaveChanges();

			}
			catch (Exception)
			{
				
				throw;
			}
			return parentCart;
		}

		public Cart UpdateCartItemQuantity(CartItem cartItem, int iQty)
		{
			var matchCart = cartItem.Cart;
			cartItem.CartItemQty += iQty;
			_container.SaveChanges();
			return matchCart;
		}

		public void DeleteCart(Cart cart)
		{
			try
			{
				foreach (var cartItem in cart.CartItems)
				{
					_container.CartItems.DeleteObject(cartItem);
				}
				_container.Carts.DeleteObject(cart);
				_container.SaveChanges();
			}
			catch (Exception)
			{
				
				throw;
			}
		}

		public void MigrateCart(Cart cart, string userId)
		{
			cart.SessionId = userId;
			_container.SaveChanges();
		}

		public IEnumerable<Cart> GetLatest(int? iTopLatest)
		{
			int intTopLatest = iTopLatest??iTopLatest.Value;
			var latestCart = (from cart in _container.Carts
							  orderby cart.CreatedDate descending
							  select cart).Take(intTopLatest);
			return latestCart;
		}

		public void Add(Cart objT)
		{
			throw new NotImplementedException();
		}

		public void Remove(Cart objT)
		{
			throw new NotImplementedException();
		}

		public void Update(Cart objT)
		{
			throw new NotImplementedException();
		}

		public Cart GetById(int iID)
		{
			var matchedCart = (from cart in _container.Carts
							   where cart.RecordId == iID
							   select cart).FirstOrDefault();
			return matchedCart;
		}

		public Cart GetCartByRecordId(string sId) {
			int iId = Int32.Parse(sId);
			var matchedCart = (from cart in _container.Carts
							   where cart.RecordId == iId
							   select cart).FirstOrDefault();
			return matchedCart;
		}

		public Cart GetById(string sID)
		{
			int iId = Int32.Parse(sID);
			return GetById(iId);
		}

		public IEnumerable<Cart> GetAll()
		{
			return _container.Carts.ToList();
		}

		public IEnumerable<Cart> GetTopRated(int? iTop)
		{
			throw new NotImplementedException();
		}



		public int GetCartItemsCount(int iRecordId)
		{
			var matchedCart = GetCartByRecordId(iRecordId.ToString());
			return GetCartItemsCount(matchedCart);
		 }


		public int GetCartItemsCount(Cart cart)
		{
			UpdateReCalItemsCount(cart);
			return cart.CartQty;

		}


		public List<CartItem> GetCartItems(string sId)
		{
			var matchedCart = GetCartByRecordId(sId.ToString());
			return GetCartItems(matchedCart);
		}

		public List<CartItem> GetCartItems(Cart cart)
		{
			List<CartItem> oReturnItems = null;
			if(cart!=null)
				oReturnItems = cart.CartItems.ToList();
			return oReturnItems;
		}


		public Order CreateOrder(CheckOutModel checkoutModel,Cart cart,int iUserID)
		{
			Order oNewOrder = new Order();
			decimal dTotalSales = 0;
			oNewOrder.OrderDate = DateTime.Now;
			oNewOrder.ShippingAddress1 = checkoutModel.ShippingAddress1;
			oNewOrder.ShippingAddress2 = checkoutModel.ShippingAddress2;
			oNewOrder.CreatedDate = DateTime.Now;
			oNewOrder.Postcode = checkoutModel.PostCode;
			oNewOrder.TotalOrderPrice = 0;
			oNewOrder.UserUserId = iUserID;

			_container.Orders.AddObject(oNewOrder);
			_container.SaveChanges();

			var cartItems = cart.CartItems.ToList();
			foreach (var cartItem in cartItems)
			{
				decimal dSubTotal = cartItem.CartItemQty * cartItem.Product.ProductUnitPrice;
				OrderDetail oDataDetail = new OrderDetail();
				oDataDetail.OrderOrderId = oNewOrder.OrderId;
				oDataDetail.Quantity = cartItem.CartItemQty;
				oDataDetail.UnitPrice = cartItem.Product.ProductUnitPrice;
                oDataDetail.ProductProductId = cartItem.ProductProductId;
				dTotalSales += dSubTotal;
				_container.OrderDetails.AddObject(oDataDetail);
				_container.SaveChanges();
			}

			oNewOrder.TotalOrderPrice = dTotalSales;
			_container.SaveChanges();
			return oNewOrder;
		}
	}
}